"""
服务层测试基类
提供服务层测试的通用功能和基础设置
"""

from typing import Any, Dict, Optional
from unittest.mock import Mock, patch
from sqlalchemy.orm import Session

from tests.utils import (
    mock_db_session,
    create_mock_user,
    create_mock_role,
    create_mock_permission
)


class BaseServiceTest:
    """服务层测试基类"""
    
    # 模拟对象
    mock_db: Optional[Mock] = None
    mock_user: Optional[Mock] = None
    mock_role: Optional[Mock] = None
    mock_permission: Optional[Mock] = None
    
    # 测试数据
    test_data: Dict[str, Any] = {}
    
    def setup_method(self):
        """每个测试方法前的设置"""
        # 创建模拟数据库会话
        self.mock_db = mock_db_session()
        
        # 创建模拟用户、角色和权限
        self.mock_user = create_mock_user()
        self.mock_role = create_mock_role()
        self.mock_permission = create_mock_permission()
        
        # 初始化测试数据
        self.test_data = {
            "user": self.mock_user,
            "role": self.mock_role,
            "permission": self.mock_permission
        }
    
    def teardown_method(self):
        """每个测试方法后的清理"""
        pass
    
    def create_test_user(self, user_id: int = 1, **kwargs) -> Mock:
        """创建测试用户"""
        return create_mock_user(user_id, **kwargs)
    
    def create_test_role(self, role_id: int = 1, **kwargs) -> Mock:
        """创建测试角色"""
        return create_mock_role(role_id, **kwargs)
    
    def create_test_permission(self, permission_id: int = 1, **kwargs) -> Mock:
        """创建测试权限"""
        return create_mock_permission(permission_id, **kwargs)
    
    def setup_mock_query(self, model_class, return_value=None):
        """设置模拟查询"""
        mock_query = Mock()
        mock_query.filter = Mock(return_value=mock_query)
        mock_query.filter_by = Mock(return_value=mock_query)
        mock_query.first = Mock(return_value=return_value)
        mock_query.all = Mock(return_value=return_value if isinstance(return_value, list) else [return_value])
        mock_query.one_or_none = Mock(return_value=return_value)
        
        self.mock_db.query = Mock(return_value=mock_query)
        return mock_query
    
    def setup_mock_add(self, return_value=None):
        """设置模拟添加操作"""
        self.mock_db.add = Mock()
        if return_value:
            self.mock_db.commit = Mock()
            self.mock_db.refresh = Mock(side_effect=lambda obj: setattr(obj, 'id', getattr(return_value, 'id', 1)))
    
    def setup_mock_delete(self):
        """设置模拟删除操作"""
        self.mock_db.delete = Mock()
        self.mock_db.commit = Mock()
    
    def assert_mock_called_with(self, mock_obj, expected_args=None, expected_kwargs=None):
        """断言模拟对象被调用"""
        assert mock_obj.called, "Mock object was not called"
        
        if expected_args:
            call_args = mock_obj.call_args[0] if mock_obj.call_args else ()
            assert call_args == expected_args, f"Expected args {expected_args}, got {call_args}"
        
        if expected_kwargs:
            call_kwargs = mock_obj.call_args[1] if mock_obj.call_args else {}
            assert call_kwargs == expected_kwargs, f"Expected kwargs {expected_kwargs}, got {call_kwargs}"
    
    def assert_mock_called_once_with(self, mock_obj, expected_args=None, expected_kwargs=None):
        """断言模拟对象被调用一次"""
        assert mock_obj.call_count == 1, f"Mock object was called {mock_obj.call_count} times, expected 1"
        self.assert_mock_called_with(mock_obj, expected_args, expected_kwargs)
    
    def assert_mock_not_called(self, mock_obj):
        """断言模拟对象未被调用"""
        assert not mock_obj.called, "Mock object was called unexpectedly"


# 为兼容性提供全局函数
def setup_mock_db() -> Mock:
    """设置模拟数据库"""
    return mock_db_session()


def setup_test_user(user_id: int = 1, **kwargs) -> Mock:
    """设置测试用户"""
    return create_mock_user(user_id, **kwargs)


def setup_test_role(role_id: int = 1, **kwargs) -> Mock:
    """设置测试角色"""
    return create_mock_role(role_id, **kwargs)


def setup_test_permission(permission_id: int = 1, **kwargs) -> Mock:
    """设置测试权限"""
    return create_mock_permission(permission_id, **kwargs)